1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package scouter.javassist;
18
19 import scouter.javassist.CannotCompileException;
20 import scouter.javassist.ClassMap;
21 import scouter.javassist.ClassPool;
22 import scouter.javassist.CodeConverter;
23 import scouter.javassist.CtClass;
24 import scouter.javassist.CtConstructor;
25 import scouter.javassist.CtField;
26 import scouter.javassist.CtMember;
27 import scouter.javassist.CtPrimitiveType;
28 import scouter.javassist.Modifier;
29 import scouter.javassist.NotFoundException;
30 import scouter.javassist.bytecode.AccessFlag;
31 import scouter.javassist.bytecode.AnnotationsAttribute;
32 import scouter.javassist.bytecode.AttributeInfo;
33 import scouter.javassist.bytecode.BadBytecode;
34 import scouter.javassist.bytecode.Bytecode;
35 import scouter.javassist.bytecode.CodeAttribute;
36 import scouter.javassist.bytecode.CodeIterator;
37 import scouter.javassist.bytecode.ConstPool;
38 import scouter.javassist.bytecode.Descriptor;
39 import scouter.javassist.bytecode.ExceptionsAttribute;
40 import scouter.javassist.bytecode.LineNumberAttribute;
41 import scouter.javassist.bytecode.LocalVariableAttribute;
42 import scouter.javassist.bytecode.LocalVariableTypeAttribute;
43 import scouter.javassist.bytecode.MethodInfo;
44 import scouter.javassist.bytecode.Opcode;
45 import scouter.javassist.bytecode.ParameterAnnotationsAttribute;
46 import scouter.javassist.bytecode.SignatureAttribute;
47 import scouter.javassist.bytecode.StackMap;
48 import scouter.javassist.bytecode.StackMapTable;
49 import scouter.javassist.compiler.CompileError;
50 import scouter.javassist.compiler.Javac;
51 import scouter.javassist.expr.ExprEditor;
52
53
54
55
56
57
58
59
60
61
62
63
64 public abstract class CtBehavior extends CtMember {
65 protected MethodInfo methodInfo;
66
67 protected CtBehavior(CtClass clazz, MethodInfo minfo) {
68 super(clazz);
69 methodInfo = minfo;
70 }
71
72
73
74
75 void copy(CtBehavior src, boolean isCons, ClassMap map)
76 throws CannotCompileException
77 {
78 CtClass declaring = declaringClass;
79 MethodInfo srcInfo = src.methodInfo;
80 CtClass srcClass = src.getDeclaringClass();
81 ConstPool cp = declaring.getClassFile2().getConstPool();
82
83 map = new ClassMap(map);
84 map.put(srcClass.getName(), declaring.getName());
85 try {
86 boolean patch = false;
87 CtClass srcSuper = srcClass.getSuperclass();
88 CtClass destSuper = declaring.getSuperclass();
89 String destSuperName = null;
90 if (srcSuper != null && destSuper != null) {
91 String srcSuperName = srcSuper.getName();
92 destSuperName = destSuper.getName();
93 if (!srcSuperName.equals(destSuperName))
94 if (srcSuperName.equals(CtClass.javaLangObject))
95 patch = true;
96 else
97 map.putIfNone(srcSuperName, destSuperName);
98 }
99
100
101 methodInfo = new MethodInfo(cp, srcInfo.getName(), srcInfo, map);
102 if (isCons && patch)
103 methodInfo.setSuperclass(destSuperName);
104 }
105 catch (NotFoundException e) {
106 throw new CannotCompileException(e);
107 }
108 catch (BadBytecode e) {
109 throw new CannotCompileException(e);
110 }
111 }
112
113 protected void extendToString(StringBuffer buffer) {
114 buffer.append(' ');
115 buffer.append(getName());
116 buffer.append(' ');
117 buffer.append(methodInfo.getDescriptor());
118 }
119
120
121
122
123
124
125
126 public abstract String getLongName();
127
128
129
130
131
132
133
134
135
136
137
138
139 public MethodInfo getMethodInfo() {
140 declaringClass.checkModify();
141 return methodInfo;
142 }
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163 public MethodInfo getMethodInfo2() { return methodInfo; }
164
165
166
167
168
169
170
171
172 public int getModifiers() {
173 return AccessFlag.toModifier(methodInfo.getAccessFlags());
174 }
175
176
177
178
179
180
181
182
183
184
185 public void setModifiers(int mod) {
186 declaringClass.checkModify();
187 methodInfo.setAccessFlags(AccessFlag.of(mod));
188 }
189
190
191
192
193
194
195
196
197
198 public boolean hasAnnotation(String typeName) {
199 MethodInfo mi = getMethodInfo2();
200 AnnotationsAttribute ainfo = (AnnotationsAttribute)
201 mi.getAttribute(AnnotationsAttribute.invisibleTag);
202 AnnotationsAttribute ainfo2 = (AnnotationsAttribute)
203 mi.getAttribute(AnnotationsAttribute.visibleTag);
204 return CtClassType.hasAnnotationType(typeName,
205 getDeclaringClass().getClassPool(),
206 ainfo, ainfo2);
207 }
208
209
210
211
212
213
214
215
216
217
218
219
220 public Object getAnnotation(Class clz) throws ClassNotFoundException {
221 MethodInfo mi = getMethodInfo2();
222 AnnotationsAttribute ainfo = (AnnotationsAttribute)
223 mi.getAttribute(AnnotationsAttribute.invisibleTag);
224 AnnotationsAttribute ainfo2 = (AnnotationsAttribute)
225 mi.getAttribute(AnnotationsAttribute.visibleTag);
226 return CtClassType.getAnnotationType(clz,
227 getDeclaringClass().getClassPool(),
228 ainfo, ainfo2);
229 }
230
231
232
233
234
235
236
237
238 public Object[] getAnnotations() throws ClassNotFoundException {
239 return getAnnotations(false);
240 }
241
242
243
244
245
246
247
248
249
250
251 public Object[] getAvailableAnnotations(){
252 try{
253 return getAnnotations(true);
254 }
255 catch (ClassNotFoundException e){
256 throw new RuntimeException("Unexpected exception", e);
257 }
258 }
259
260 private Object[] getAnnotations(boolean ignoreNotFound)
261 throws ClassNotFoundException
262 {
263 MethodInfo mi = getMethodInfo2();
264 AnnotationsAttribute ainfo = (AnnotationsAttribute)
265 mi.getAttribute(AnnotationsAttribute.invisibleTag);
266 AnnotationsAttribute ainfo2 = (AnnotationsAttribute)
267 mi.getAttribute(AnnotationsAttribute.visibleTag);
268 return CtClassType.toAnnotationType(ignoreNotFound,
269 getDeclaringClass().getClassPool(),
270 ainfo, ainfo2);
271 }
272
273
274
275
276
277
278
279
280
281
282
283
284 public Object[][] getParameterAnnotations() throws ClassNotFoundException {
285 return getParameterAnnotations(false);
286 }
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301 public Object[][] getAvailableParameterAnnotations(){
302 try {
303 return getParameterAnnotations(true);
304 }
305 catch(ClassNotFoundException e) {
306 throw new RuntimeException("Unexpected exception", e);
307 }
308 }
309
310 Object[][] getParameterAnnotations(boolean ignoreNotFound)
311 throws ClassNotFoundException
312 {
313 MethodInfo mi = getMethodInfo2();
314 ParameterAnnotationsAttribute ainfo = (ParameterAnnotationsAttribute)
315 mi.getAttribute(ParameterAnnotationsAttribute.invisibleTag);
316 ParameterAnnotationsAttribute ainfo2 = (ParameterAnnotationsAttribute)
317 mi.getAttribute(ParameterAnnotationsAttribute.visibleTag);
318 return CtClassType.toAnnotationType(ignoreNotFound,
319 getDeclaringClass().getClassPool(),
320 ainfo, ainfo2, mi);
321 }
322
323
324
325
326 public CtClass[] getParameterTypes() throws NotFoundException {
327 return Descriptor.getParameterTypes(methodInfo.getDescriptor(),
328 declaringClass.getClassPool());
329 }
330
331
332
333
334 CtClass getReturnType0() throws NotFoundException {
335 return Descriptor.getReturnType(methodInfo.getDescriptor(),
336 declaringClass.getClassPool());
337 }
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356 public String getSignature() {
357 return methodInfo.getDescriptor();
358 }
359
360
361
362
363
364
365
366
367 public String getGenericSignature() {
368 SignatureAttribute sa
369 = (SignatureAttribute)methodInfo.getAttribute(SignatureAttribute.tag);
370 return sa == null ? null : sa.getSignature();
371 }
372
373
374
375
376
377
378
379
380
381
382
383 public void setGenericSignature(String sig) {
384 declaringClass.checkModify();
385 methodInfo.addAttribute(new SignatureAttribute(methodInfo.getConstPool(), sig));
386 }
387
388
389
390
391
392
393 public CtClass[] getExceptionTypes() throws NotFoundException {
394 String[] exceptions;
395 ExceptionsAttribute ea = methodInfo.getExceptionsAttribute();
396 if (ea == null)
397 exceptions = null;
398 else
399 exceptions = ea.getExceptions();
400
401 return declaringClass.getClassPool().get(exceptions);
402 }
403
404
405
406
407 public void setExceptionTypes(CtClass[] types) throws NotFoundException {
408 declaringClass.checkModify();
409 if (types == null || types.length == 0) {
410 methodInfo.removeExceptionsAttribute();
411 return;
412 }
413
414 String[] names = new String[types.length];
415 for (int i = 0; i < types.length; ++i)
416 names[i] = types[i].getName();
417
418 ExceptionsAttribute ea = methodInfo.getExceptionsAttribute();
419 if (ea == null) {
420 ea = new ExceptionsAttribute(methodInfo.getConstPool());
421 methodInfo.setExceptionsAttribute(ea);
422 }
423
424 ea.setExceptions(names);
425 }
426
427
428
429
430 public abstract boolean isEmpty();
431
432
433
434
435
436
437
438
439
440 public void setBody(String src) throws CannotCompileException {
441 setBody(src, null, null);
442 }
443
444
445
446
447
448
449
450
451
452
453
454
455
456 public void setBody(String src,
457 String delegateObj, String delegateMethod)
458 throws CannotCompileException
459 {
460 CtClass cc = declaringClass;
461 cc.checkModify();
462 try {
463 Javac jv = new Javac(cc);
464 if (delegateMethod != null)
465 jv.recordProceed(delegateObj, delegateMethod);
466
467 Bytecode b = jv.compileBody(this, src);
468 methodInfo.setCodeAttribute(b.toCodeAttribute());
469 methodInfo.setAccessFlags(methodInfo.getAccessFlags()
470 & ~AccessFlag.ABSTRACT);
471 methodInfo.rebuildStackMapIf6(cc.getClassPool(), cc.getClassFile2());
472 declaringClass.rebuildClassFile();
473 }
474 catch (CompileError e) {
475 throw new CannotCompileException(e);
476 } catch (BadBytecode e) {
477 throw new CannotCompileException(e);
478 }
479 }
480
481 static void setBody0(CtClass srcClass, MethodInfo srcInfo,
482 CtClass destClass, MethodInfo destInfo,
483 ClassMap map)
484 throws CannotCompileException
485 {
486 destClass.checkModify();
487
488 map = new ClassMap(map);
489 map.put(srcClass.getName(), destClass.getName());
490 try {
491 CodeAttribute cattr = srcInfo.getCodeAttribute();
492 if (cattr != null) {
493 ConstPool cp = destInfo.getConstPool();
494 CodeAttribute ca = (CodeAttribute)cattr.copy(cp, map);
495 destInfo.setCodeAttribute(ca);
496
497 }
498 }
499 catch (CodeAttribute.RuntimeCopyException e) {
500
501
502 throw new CannotCompileException(e);
503 }
504
505 destInfo.setAccessFlags(destInfo.getAccessFlags()
506 & ~AccessFlag.ABSTRACT);
507 destClass.rebuildClassFile();
508 }
509
510
511
512
513
514
515
516
517
518
519
520
521 public byte[] getAttribute(String name) {
522 AttributeInfo ai = methodInfo.getAttribute(name);
523 if (ai == null)
524 return null;
525 else
526 return ai.get();
527 }
528
529
530
531
532
533
534
535
536
537
538
539 public void setAttribute(String name, byte[] data) {
540 declaringClass.checkModify();
541 methodInfo.addAttribute(new AttributeInfo(methodInfo.getConstPool(),
542 name, data));
543 }
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562 public void useCflow(String name) throws CannotCompileException {
563 CtClass cc = declaringClass;
564 cc.checkModify();
565 ClassPool pool = cc.getClassPool();
566 String fname;
567 int i = 0;
568 while (true) {
569 fname = "_cflow$" + i++;
570 try {
571 cc.getDeclaredField(fname);
572 }
573 catch(NotFoundException e) {
574 break;
575 }
576 }
577
578 pool.recordCflow(name, declaringClass.getName(), fname);
579 try {
580 CtClass type = pool.get("javassist.runtime.Cflow");
581 CtField field = new CtField(type, fname, cc);
582 field.setModifiers(Modifier.PUBLIC | Modifier.STATIC);
583 cc.addField(field, CtField.Initializer.byNew(type));
584 insertBefore(fname + ".enter();", false);
585 String src = fname + ".exit();";
586 insertAfter(src, true);
587 }
588 catch (NotFoundException e) {
589 throw new CannotCompileException(e);
590 }
591 }
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608 public void addLocalVariable(String name, CtClass type)
609 throws CannotCompileException
610 {
611 declaringClass.checkModify();
612 ConstPool cp = methodInfo.getConstPool();
613 CodeAttribute ca = methodInfo.getCodeAttribute();
614 if (ca == null)
615 throw new CannotCompileException("no method body");
616
617 LocalVariableAttribute va = (LocalVariableAttribute)ca.getAttribute(
618 LocalVariableAttribute.tag);
619 if (va == null) {
620 va = new LocalVariableAttribute(cp);
621 ca.getAttributes().add(va);
622 }
623
624 int maxLocals = ca.getMaxLocals();
625 String desc = Descriptor.of(type);
626 va.addEntry(0, ca.getCodeLength(),
627 cp.addUtf8Info(name), cp.addUtf8Info(desc), maxLocals);
628 ca.setMaxLocals(maxLocals + Descriptor.dataSize(desc));
629 }
630
631
632
633
634 public void insertParameter(CtClass type)
635 throws CannotCompileException
636 {
637 declaringClass.checkModify();
638 String desc = methodInfo.getDescriptor();
639 String desc2 = Descriptor.insertParameter(type, desc);
640 try {
641 addParameter2(Modifier.isStatic(getModifiers()) ? 0 : 1, type, desc);
642 }
643 catch (BadBytecode e) {
644 throw new CannotCompileException(e);
645 }
646
647 methodInfo.setDescriptor(desc2);
648 }
649
650
651
652
653 public void addParameter(CtClass type)
654 throws CannotCompileException
655 {
656 declaringClass.checkModify();
657 String desc = methodInfo.getDescriptor();
658 String desc2 = Descriptor.appendParameter(type, desc);
659 int offset = Modifier.isStatic(getModifiers()) ? 0 : 1;
660 try {
661 addParameter2(offset + Descriptor.paramSize(desc), type, desc);
662 }
663 catch (BadBytecode e) {
664 throw new CannotCompileException(e);
665 }
666
667 methodInfo.setDescriptor(desc2);
668 }
669
670 private void addParameter2(int where, CtClass type, String desc)
671 throws BadBytecode
672 {
673 CodeAttribute ca = methodInfo.getCodeAttribute();
674 if (ca != null) {
675 int size = 1;
676 char typeDesc = 'L';
677 int classInfo = 0;
678 if (type.isPrimitive()) {
679 CtPrimitiveType cpt = (CtPrimitiveType)type;
680 size = cpt.getDataSize();
681 typeDesc = cpt.getDescriptor();
682 }
683 else
684 classInfo = methodInfo.getConstPool().addClassInfo(type);
685
686 ca.insertLocalVar(where, size);
687 LocalVariableAttribute va
688 = (LocalVariableAttribute)ca.getAttribute(LocalVariableAttribute.tag);
689 if (va != null)
690 va.shiftIndex(where, size);
691
692 LocalVariableTypeAttribute lvta
693 = (LocalVariableTypeAttribute)ca.getAttribute(LocalVariableTypeAttribute.tag);
694 if (lvta != null)
695 lvta.shiftIndex(where, size);
696
697 StackMapTable smt = (StackMapTable)ca.getAttribute(StackMapTable.tag);
698 if (smt != null)
699 smt.insertLocal(where, StackMapTable.typeTagOf(typeDesc), classInfo);
700
701 StackMap sm = (StackMap)ca.getAttribute(StackMap.tag);
702 if (sm != null)
703 sm.insertLocal(where, StackMapTable.typeTagOf(typeDesc), classInfo);
704 }
705 }
706
707
708
709
710
711
712 public void instrument(CodeConverter converter)
713 throws CannotCompileException
714 {
715 declaringClass.checkModify();
716 ConstPool cp = methodInfo.getConstPool();
717 converter.doit(getDeclaringClass(), methodInfo, cp);
718 }
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733 public void instrument(ExprEditor editor)
734 throws CannotCompileException
735 {
736
737
738 if (declaringClass.isFrozen())
739 declaringClass.checkModify();
740
741 if (editor.doit(declaringClass, methodInfo))
742 declaringClass.checkModify();
743 }
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762 public void insertBefore(String src) throws CannotCompileException {
763 insertBefore(src, true);
764 }
765
766 private void insertBefore(String src, boolean rebuild)
767 throws CannotCompileException
768 {
769 CtClass cc = declaringClass;
770 cc.checkModify();
771 CodeAttribute ca = methodInfo.getCodeAttribute();
772 if (ca == null)
773 throw new CannotCompileException("no method body");
774
775 CodeIterator iterator = ca.iterator();
776 Javac jv = new Javac(cc);
777 try {
778 int nvars = jv.recordParams(getParameterTypes(),
779 Modifier.isStatic(getModifiers()));
780 jv.recordParamNames(ca, nvars);
781 jv.recordLocalVariables(ca, 0);
782 jv.recordType(getReturnType0());
783 jv.compileStmnt(src);
784 Bytecode b = jv.getBytecode();
785 int stack = b.getMaxStack();
786 int locals = b.getMaxLocals();
787
788 if (stack > ca.getMaxStack())
789 ca.setMaxStack(stack);
790
791 if (locals > ca.getMaxLocals())
792 ca.setMaxLocals(locals);
793
794 int pos = iterator.insertEx(b.get());
795 iterator.insert(b.getExceptionTable(), pos);
796 if (rebuild)
797 methodInfo.rebuildStackMapIf6(cc.getClassPool(), cc.getClassFile2());
798 }
799 catch (NotFoundException e) {
800 throw new CannotCompileException(e);
801 }
802 catch (CompileError e) {
803 throw new CannotCompileException(e);
804 }
805 catch (BadBytecode e) {
806 throw new CannotCompileException(e);
807 }
808 }
809
810
811
812
813
814
815
816
817
818 public void insertAfter(String src)
819 throws CannotCompileException
820 {
821 insertAfter(src, false);
822 }
823
824
825
826
827
828
829
830
831
832
833
834
835
836 public void insertAfter(String src, boolean asFinally)
837 throws CannotCompileException
838 {
839 CtClass cc = declaringClass;
840 cc.checkModify();
841 ConstPool pool = methodInfo.getConstPool();
842 CodeAttribute ca = methodInfo.getCodeAttribute();
843 if (ca == null)
844 throw new CannotCompileException("no method body");
845
846 CodeIterator iterator = ca.iterator();
847 int retAddr = ca.getMaxLocals();
848 Bytecode b = new Bytecode(pool, 0, retAddr + 1);
849 b.setStackDepth(ca.getMaxStack() + 1);
850 Javac jv = new Javac(b, cc);
851 try {
852 int nvars = jv.recordParams(getParameterTypes(),
853 Modifier.isStatic(getModifiers()));
854 jv.recordParamNames(ca, nvars);
855 CtClass rtype = getReturnType0();
856 int varNo = jv.recordReturnType(rtype, true);
857 jv.recordLocalVariables(ca, 0);
858
859
860 int handlerLen = insertAfterHandler(asFinally, b, rtype, varNo,
861 jv, src);
862 int handlerPos = iterator.getCodeLength();
863 if (asFinally)
864 ca.getExceptionTable().add(getStartPosOfBody(ca), handlerPos, handlerPos, 0);
865
866 int adviceLen = 0;
867 int advicePos = 0;
868 boolean noReturn = true;
869 while (iterator.hasNext()) {
870 int pos = iterator.next();
871 if (pos >= handlerPos)
872 break;
873
874 int c = iterator.byteAt(pos);
875 if (c == Opcode.ARETURN || c == Opcode.IRETURN
876 || c == Opcode.FRETURN || c == Opcode.LRETURN
877 || c == Opcode.DRETURN || c == Opcode.RETURN) {
878 if (noReturn) {
879
880 adviceLen = insertAfterAdvice(b, jv, src, pool, rtype, varNo);
881 handlerPos = iterator.append(b.get());
882 iterator.append(b.getExceptionTable(), handlerPos);
883 advicePos = iterator.getCodeLength() - adviceLen;
884 handlerLen = advicePos - handlerPos;
885 noReturn = false;
886 }
887 insertGoto(iterator, advicePos, pos);
888 advicePos = iterator.getCodeLength() - adviceLen;
889 handlerPos = advicePos - handlerLen;
890 }
891 }
892
893 if (noReturn) {
894 handlerPos = iterator.append(b.get());
895 iterator.append(b.getExceptionTable(), handlerPos);
896 }
897
898 ca.setMaxStack(b.getMaxStack());
899 ca.setMaxLocals(b.getMaxLocals());
900 methodInfo.rebuildStackMapIf6(cc.getClassPool(), cc.getClassFile2());
901 }
902 catch (NotFoundException e) {
903 throw new CannotCompileException(e);
904 }
905 catch (CompileError e) {
906 throw new CannotCompileException(e);
907 }
908 catch (BadBytecode e) {
909 throw new CannotCompileException(e);
910 }
911 }
912
913 private int insertAfterAdvice(Bytecode code, Javac jv, String src,
914 ConstPool cp, CtClass rtype, int varNo)
915 throws CompileError
916 {
917 int pc = code.currentPc();
918 if (rtype == CtClass.voidType) {
919 code.addOpcode(Opcode.ACONST_NULL);
920 code.addAstore(varNo);
921 jv.compileStmnt(src);
922 code.addOpcode(Opcode.RETURN);
923 if (code.getMaxLocals() < 1)
924 code.setMaxLocals(1);
925 }
926 else {
927 code.addStore(varNo, rtype);
928 jv.compileStmnt(src);
929 code.addLoad(varNo, rtype);
930 if (rtype.isPrimitive())
931 code.addOpcode(((CtPrimitiveType)rtype).getReturnOp());
932 else
933 code.addOpcode(Opcode.ARETURN);
934 }
935
936 return code.currentPc() - pc;
937 }
938
939
940
941
942 private void insertGoto(CodeIterator iterator, int subr, int pos)
943 throws BadBytecode
944 {
945 iterator.setMark(subr);
946
947 iterator.writeByte(Opcode.NOP, pos);
948 boolean wide = subr + 2 - pos > Short.MAX_VALUE;
949 int len = wide ? 4 : 2;
950 CodeIterator.Gap gap = iterator.insertGapAt(pos, len, false);
951 pos = gap.position + gap.length - len;
952 int offset = iterator.getMark() - pos;
953 if (wide) {
954 iterator.writeByte(Opcode.GOTO_W, pos);
955 iterator.write32bit(offset, pos + 1);
956 }
957 else if (offset <= Short.MAX_VALUE) {
958 iterator.writeByte(Opcode.GOTO, pos);
959 iterator.write16bit(offset, pos + 1);
960 }
961 else {
962 if (gap.length < 4) {
963 CodeIterator.Gap gap2 = iterator.insertGapAt(gap.position, 2, false);
964 pos = gap2.position + gap2.length + gap.length - 4;
965 }
966
967 iterator.writeByte(Opcode.GOTO_W, pos);
968 iterator.write32bit(iterator.getMark() - pos, pos + 1);
969 }
970 }
971
972
973
974 private int insertAfterHandler(boolean asFinally, Bytecode b,
975 CtClass rtype, int returnVarNo,
976 Javac javac, String src)
977 throws CompileError
978 {
979 if (!asFinally)
980 return 0;
981
982 int var = b.getMaxLocals();
983 b.incMaxLocals(1);
984 int pc = b.currentPc();
985 b.addAstore(var);
986 if (rtype.isPrimitive()) {
987 char c = ((CtPrimitiveType)rtype).getDescriptor();
988 if (c == 'D') {
989 b.addDconst(0.0);
990 b.addDstore(returnVarNo);
991 }
992 else if (c == 'F') {
993 b.addFconst(0);
994 b.addFstore(returnVarNo);
995 }
996 else if (c == 'J') {
997 b.addLconst(0);
998 b.addLstore(returnVarNo);
999 }
1000 else if (c == 'V') {
1001 b.addOpcode(Opcode.ACONST_NULL);
1002 b.addAstore(returnVarNo);
1003 }
1004 else {
1005 b.addIconst(0);
1006 b.addIstore(returnVarNo);
1007 }
1008 }
1009 else {
1010 b.addOpcode(Opcode.ACONST_NULL);
1011 b.addAstore(returnVarNo);
1012 }
1013
1014 javac.compileStmnt(src);
1015 b.addAload(var);
1016 b.addOpcode(Opcode.ATHROW);
1017 return b.currentPc() - pc;
1018 }
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080 public void addCatch(String src, CtClass exceptionType)
1081 throws CannotCompileException
1082 {
1083 addCatch(src, exceptionType, "$e");
1084 }
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098 public void addCatch(String src, CtClass exceptionType,
1099 String exceptionName)
1100 throws CannotCompileException
1101 {
1102 CtClass cc = declaringClass;
1103 cc.checkModify();
1104 ConstPool cp = methodInfo.getConstPool();
1105 CodeAttribute ca = methodInfo.getCodeAttribute();
1106 CodeIterator iterator = ca.iterator();
1107 Bytecode b = new Bytecode(cp, ca.getMaxStack(), ca.getMaxLocals());
1108 b.setStackDepth(1);
1109 Javac jv = new Javac(b, cc);
1110 try {
1111 jv.recordParams(getParameterTypes(),
1112 Modifier.isStatic(getModifiers()));
1113 int var = jv.recordVariable(exceptionType, exceptionName);
1114 b.addAstore(var);
1115 jv.compileStmnt(src);
1116
1117 int stack = b.getMaxStack();
1118 int locals = b.getMaxLocals();
1119
1120 if (stack > ca.getMaxStack())
1121 ca.setMaxStack(stack);
1122
1123 if (locals > ca.getMaxLocals())
1124 ca.setMaxLocals(locals);
1125
1126 int len = iterator.getCodeLength();
1127 int pos = iterator.append(b.get());
1128 ca.getExceptionTable().add(getStartPosOfBody(ca), len, len,
1129 cp.addClassInfo(exceptionType));
1130 iterator.append(b.getExceptionTable(), pos);
1131 methodInfo.rebuildStackMapIf6(cc.getClassPool(), cc.getClassFile2());
1132 }
1133 catch (NotFoundException e) {
1134 throw new CannotCompileException(e);
1135 }
1136 catch (CompileError e) {
1137 throw new CannotCompileException(e);
1138 } catch (BadBytecode e) {
1139 throw new CannotCompileException(e);
1140 }
1141 }
1142
1143
1144
1145 int getStartPosOfBody(CodeAttribute ca) throws CannotCompileException {
1146 return 0;
1147 }
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166 public int insertAt(int lineNum, String src)
1167 throws CannotCompileException
1168 {
1169 return insertAt(lineNum, true, src);
1170 }
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194 public int insertAt(int lineNum, boolean modify, String src)
1195 throws CannotCompileException
1196 {
1197 CodeAttribute ca = methodInfo.getCodeAttribute();
1198 if (ca == null)
1199 throw new CannotCompileException("no method body");
1200
1201 LineNumberAttribute ainfo
1202 = (LineNumberAttribute)ca.getAttribute(LineNumberAttribute.tag);
1203 if (ainfo == null)
1204 throw new CannotCompileException("no line number info");
1205
1206 LineNumberAttribute.Pc pc = ainfo.toNearPc(lineNum);
1207 lineNum = pc.line;
1208 int index = pc.index;
1209 if (!modify)
1210 return lineNum;
1211
1212 CtClass cc = declaringClass;
1213 cc.checkModify();
1214 CodeIterator iterator = ca.iterator();
1215 Javac jv = new Javac(cc);
1216 try {
1217 jv.recordLocalVariables(ca, index);
1218 jv.recordParams(getParameterTypes(),
1219 Modifier.isStatic(getModifiers()));
1220 jv.setMaxLocals(ca.getMaxLocals());
1221 jv.compileStmnt(src);
1222 Bytecode b = jv.getBytecode();
1223 int locals = b.getMaxLocals();
1224 int stack = b.getMaxStack();
1225 ca.setMaxLocals(locals);
1226
1227
1228
1229
1230 if (stack > ca.getMaxStack())
1231 ca.setMaxStack(stack);
1232
1233 index = iterator.insertAt(index, b.get());
1234 iterator.insert(b.getExceptionTable(), index);
1235 methodInfo.rebuildStackMapIf6(cc.getClassPool(), cc.getClassFile2());
1236 return lineNum;
1237 }
1238 catch (NotFoundException e) {
1239 throw new CannotCompileException(e);
1240 }
1241 catch (CompileError e) {
1242 throw new CannotCompileException(e);
1243 }
1244 catch (BadBytecode e) {
1245 throw new CannotCompileException(e);
1246 }
1247 }
1248 }